﻿using BookStorage.Service;
using BookStorage.Utility;
using Code.Entity;
using Code.Repsitory.AdminRoles;
using Code.Repsitory.Admins;
using Code.Services.Admins.Dto;
using IdentityModel;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using NLog;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using AutoMapper;
using Autofac.Extras.DynamicProxy;

namespace Code.Services.Admins
{
    //[Intercept(typeof(LogInterceptor))]
    public class AdminService : IAdminService
    {
        private readonly IAdminRepository adminRepository;
        private readonly IAdminRoleRepository adminRoleRepository;
        private readonly IConfiguration configuration;
        private readonly ILogger<AdminService> logger;
        private readonly IWebHostEnvironment environment;
        private readonly IHttpContextAccessor httpContext;
        private readonly IMapper mapper;

        public AdminService(
            IAdminRepository adminRepository,
            IAdminRoleRepository adminRoleRepository,
            IConfiguration configuration,
            ILogger<AdminService> logger,
            IWebHostEnvironment environment,
            IHttpContextAccessor httpContext,
            IMapper mapper
            )
        {
            this.adminRepository = adminRepository;
            this.adminRoleRepository = adminRoleRepository;
            this.configuration = configuration;
            this.logger = logger;
            this.environment = environment;
            this.httpContext = httpContext;
            this.mapper = mapper;
        }

        public async Task<ResultDto<AdminTokenDto>> Login(LoginDto loginDto)
        {
            //查用户名是否存在，loginDto
            var user = adminRepository.Query(m => m.UserName == loginDto.UserName).FirstOrDefault();
            if (user == null)
            {
                return new ResultDto<AdminTokenDto> { Code = 1, Message = "用户不存在" };
            }
            else
            {
                if (Md5Helper.MD5Hash(loginDto.Password) != user.Password)
                {
                    return new ResultDto<AdminTokenDto> { Code = 2, Message = "密码错误" };
                }
                else
                {
                    //写Session或Cookies换成JWT
                    IList<Claim> claims = new List<Claim> {
                        new Claim(JwtClaimTypes.Id,user.AdminId.ToString()),
                        new Claim(JwtClaimTypes.Name,user.UserName),
                        new Claim(ClaimTypes.Name,user.UserName),
                    };

                    //获取当前用户的角色
                    adminRoleRepository.Query(m=>m.AdminId == user.AdminId).ToList().ForEach(m =>{
                        claims.Add(new Claim(ClaimTypes.Role, m.RoleId.ToString()));
                    });

                    //JWT密钥
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:key"]));

                    //算法
                    var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    //过期时间
                    DateTime expires = DateTime.UtcNow.AddHours(10);


                    //Payload负载
                    var token = new JwtSecurityToken(
                        issuer: configuration["JwtConfig:Issuer"],
                        audience: configuration["JwtConfig:Audience"],
                        claims: claims,
                        notBefore: DateTime.UtcNow,
                        expires: expires,
                        signingCredentials: cred
                        );

                    var handler = new JwtSecurityTokenHandler();

                    //生成令牌
                    string jwt = handler.WriteToken(token);

                    return new ResultDto<AdminTokenDto>
                    {
                        Code = 0,
                        Data = new AdminTokenDto
                        {
                            UserName = loginDto.UserName,
                            Password = loginDto.Password,
                            Token = jwt
                        }
                    };
                }
            }
        }

        public async Task<ResultDto<List<AdminDto>>> AdminList(int PageIndex, int PageSize = 10)
        {
            var list = adminRepository.QueryAll().Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();

            return new ResultDto<List<AdminDto>>
            {
                Code = 200,
                Data = mapper.Map<List<AdminDto>>(list)
            };
        }

        public ResultDto<AdminDto> Create(AdminCreateOrUpdateDto dto)
        {
            if (!adminRepository.Queryable().Any(m => m.UserName == dto.UserName))
            {
                var entity = new Admin
                {
                    Avatar = dto.Avatar,
                    CreateTime = DateTime.Now,
                    Password = Md5Helper.MD5Hash(dto.Password),
                    UserName = dto.UserName,
                    AdminRoles = dto.intRoles.Select(m => new AdminRole
                    {
                        RoleId = m
                    }).ToList()
                };

                //1,3  数组  字符串
                var admin = adminRepository.Insert(entity);

                return new ResultDto<AdminDto>
                {
                    Code = 200,
                    Data = new AdminDto
                    {
                        Avatar = dto.Avatar,
                        CreateTime = DateTime.Now,
                        UserName = dto.UserName,
                        AdminId = admin.AdminId
                    }
                };
            }
            else
            {
                return new ResultDto<AdminDto>
                {
                    Code = 201,
                    Message = "已存在此用户"
                };
            }
        }

        public ResultDto<AdminDto> Update(AdminCreateOrUpdateDto dto)
        {
            if (adminRepository.Queryable().Any(m => m.UserName == dto.UserName && m.AdminId != dto.AdminId))
            {
                return new ResultDto<AdminDto>
                {
                    Code = 201,
                    Message = "已存在此用户"
                };
            }
            else
            {
                var entity = adminRepository.QueryFirst(dto.AdminId);
                entity.UserName = dto.UserName;
                entity.Avatar = dto.Avatar;

                //删除中间表
                adminRoleRepository.Delete(m => m.AdminId == dto.AdminId);

                //重新添加中间表
                foreach (var item in dto.intRoles)
                {
                    adminRoleRepository.Insert(new AdminRole
                    {
                        AdminId = dto.AdminId,
                        RoleId = item
                    });
                }

                return new ResultDto<AdminDto>
                {
                    Code = 200,
                    Data = new AdminDto
                    {
                        Avatar = dto.Avatar,
                        CreateTime = DateTime.Now,
                        UserName = dto.UserName,
                        AdminId = dto.AdminId
                    }
                };
            }
        }


        public bool Delete(int id)
        {
            try
            {
                //删除文件
                var user = adminRepository.QueryFirst(id);
                var imgPath = $"{environment.WebRootPath}{user.Avatar}";

                if(File.Exists(imgPath))
                    File.Delete(imgPath);

                adminRepository.Delete(id);
                logger.LogInformation($"删除了{user.UserName}用户");
                return true;
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                return false;
            }
        }

        public bool Delete(int[] ids)
        {
            try
            {
                //删除文件
                var user = adminRepository.Query(m=>ids.Contains(m.AdminId));
                foreach (var item in user)
                {
                    var imgPath = $"{environment.WebRootPath}{item.Avatar}";

                    if (File.Exists(imgPath))
                        File.Delete(imgPath);

                    logger.LogInformation($"删除了{item.UserName}用户");
                }                

                adminRepository.Delete(ids);
                
                return true;
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                return false;
            }
        }


        public ResultDto<AdminCreateOrUpdateDto> Edit(int Id)
        {
            var entity = adminRepository.QueryFirst(Id);
            return new ResultDto<AdminCreateOrUpdateDto>
            {
                Code = 200,
                Data = new AdminCreateOrUpdateDto
                {
                    AdminId = Id,
                    Avatar = entity.Avatar,
                    UserName = entity.UserName,
                    intRoles = adminRoleRepository.Query(m => m.AdminId == entity.AdminId)
                 .Select(x => x.RoleId).ToArray()
                }
            };
        }
    }

    public class PagedList<T>
        where T : class, new()
    {
        private int _PageIndex;
        /// <summary>
        /// 页码
        /// </summary>
        public int PageIndex
        {
            get
            {
                return _PageIndex;
            }
            set
            {
                if (_PageIndex <= 0)
                {
                    _PageIndex = 1;
                }
                else
                {
                    _PageIndex = value;
                }
            }
        }

        private int _PageSize;
        /// <summary>
        /// 每页行数
        /// </summary>
        public int PageSize
        {
            get
            {
                return _PageSize;
            }
            set
            {
                if (_PageSize <= 0)
                {
                    _PageSize = 1;
                }
                else
                {
                    _PageSize = value;
                }
            }
        }

        public int TotalCount { get; set; }

        private int _PageCount;
        public int PageCount
        {
            get
            {
                return (int)Math.Ceiling(Convert.ToDecimal((TotalCount / PageSize)));
            }
        }

        /// <summary>
        /// 页数据列表
        /// </summary>
        public IList<T> Items { get; set; }
    }
}
